/*
 * BulletPhysicsSpace.cpp
 *
 *  Created on: Sep 25, 2009
 *      Author: Falken
 */

#include <jni.h>
#include <iostream.h>
#include "BulletPhysicsSpace.h"
#include "PhysicsSpaceBridge.h"

#ifdef __cplusplus
extern "C" {
#endif

PhysicsSpaceBridge* g_physBridge = 0;

/*
 * Class:     com_jmex_physics_impl_bullet_BulletPhysicsSpace
 * Method:    step
 * Signature: (F)V
 */
JNIEXPORT void JNICALL Java_com_jmex_physics_impl_bullet_BulletNativeInvoker_step
  (JNIEnv* env, jclass invokerClass, jobject javaBulletPhysicsSpace, jfloat timestep)
{
	g_physBridge->step(env,timestep);
}

/*
 * Class:     com_jmex_physics_impl_bullet_BulletRigidBody
 * Method:    rebuildRigidBody
 * Signature: ()V
 */
JNIEXPORT jlong JNICALL Java_com_jmex_physics_impl_bullet_BulletNativeInvoker_rebuildRigidBody
  (JNIEnv* env, jclass invokerClass, jobject javaRB,
		  jfloat posX, jfloat posY, jfloat posZ,
		  jfloat rotX, jfloat rotY, jfloat rotZ, jfloat rotW,
		  jfloat scaleX, jfloat scaleY, jfloat scaleZ,
		  jfloat comX, jfloat comY, jfloat comZ,
		  jfloat linVX, jfloat linVY, jfloat linVZ,
		  jfloat angVX, jfloat angVY, jfloat angVZ,
		  jfloat mass)
{
	jlong ret = g_physBridge->buildRigidBody(env,javaRB,
											 btVector3(posX,posY,posZ),
											 btQuaternion(rotX,rotY,rotZ,rotW),
											 btVector3(scaleX,scaleY,scaleZ),
											 btTransform(btQuaternion(0,0,0,1),btVector3(comX,comY,comZ)),
											 btVector3(linVX,linVY,linVZ),
											 btVector3(angVX,angVY,angVZ),
											 mass);
	return ret;
}

/*
 * Class:     com_jmex_physics_impl_bullet_BulletNativeInvoker
 * Method:    buildJoint
 * Signature: (Ljava/lang/Object;IFFFFFFFFFFFFFFJJ)J
 */
JNIEXPORT jlong JNICALL Java_com_jmex_physics_impl_bullet_BulletNativeInvoker_buildJoint
  (JNIEnv* env, jclass invokerClass, jobject javaJoint, jint jointType,
		  jfloat rotAX, jfloat rotAY, jfloat rotAZ, jfloat rotAW,
		  jfloat transAX, jfloat transAY, jfloat transAZ,
		  jfloat rotBX, jfloat rotBY, jfloat rotBZ, jfloat rotBW,
		  jfloat transBX, jfloat transBY, jfloat transBZ,
		  jlong rbAHandle, jlong rbBHandle, jboolean collideWithSelf)
{
	jlong ret = g_physBridge->buildJoint(env,javaJoint, jointType,
										 btTransform(btQuaternion(rotAX,rotAY,rotAZ,rotAW),btVector3(transAX,transAY,transAZ)),
										 btTransform(btQuaternion(rotBX,rotBY,rotBZ,rotBW),btVector3(transBX,transBY,transBZ)),
										 rbAHandle, rbBHandle, collideWithSelf);
	return ret;
}

/*
 * Class:     com_jmex_physics_impl_bullet_BulletPhysicsSpace
 * Method:    createPhysicsWorld
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_jmex_physics_impl_bullet_BulletNativeInvoker_createPhysicsWorld
  (JNIEnv* env, jclass invokerClass, jobject javaBulletPhysicsSpace)
{

	if(g_physBridge != NULL)
	{
		jclass newExc=env->FindClass("java/lang/IllegalStateException");
		env->ThrowNew(newExc, "The physics space has already been created.");
	} else {
		g_physBridge = new PhysicsSpaceBridge(env,javaBulletPhysicsSpace);
	}
}

/*
 * Class:     com_jmex_physics_impl_bullet_BulletNativeInvoker
 * Method:    pushRigidBodyInfo
 * Signature: ([J[F[F[F[F[F[F[F[F[F[F[F[F[F)V
 */
JNIEXPORT void JNICALL Java_com_jmex_physics_impl_bullet_BulletNativeInvoker_pushRigidBodyInfo
  (JNIEnv* env, jclass invokerClass, jlongArray jmeHandles,
		  jfloatArray txs, jfloatArray tys, jfloatArray tzs,
		  jfloatArray rxs, jfloatArray rys, jfloatArray rzs, jfloatArray rws,
		  jfloatArray lvxs, jfloatArray lvys, jfloatArray lvzs,
		  jfloatArray avxs, jfloatArray avys, jfloatArray avzs)
{
	jboolean* temp = new jboolean;
	int size = env->GetArrayLength(jmeHandles);
	jlong* handles = env->GetLongArrayElements(jmeHandles,temp);
	jfloat* tx = env->GetFloatArrayElements(txs,temp);
	jfloat* ty = env->GetFloatArrayElements(tys,temp);
	jfloat* tz = env->GetFloatArrayElements(tzs,temp);
	jfloat* rx = env->GetFloatArrayElements(rxs,temp);
	jfloat* ry = env->GetFloatArrayElements(rys,temp);
	jfloat* rz = env->GetFloatArrayElements(rzs,temp);
	jfloat* rw = env->GetFloatArrayElements(rws,temp);
	jfloat* lvx = env->GetFloatArrayElements(lvxs,temp);
	jfloat* lvy = env->GetFloatArrayElements(lvys,temp);
	jfloat* lvz = env->GetFloatArrayElements(lvzs,temp);
	jfloat* avx = env->GetFloatArrayElements(avxs,temp);
	jfloat* avy = env->GetFloatArrayElements(avys,temp);
	jfloat* avz = env->GetFloatArrayElements(avzs,temp);

	for(int loop=0; loop<size; loop++)
		g_physBridge->setRigidBodyInfo(handles[loop],
				tx[loop],ty[loop],tz[loop],
				rx[loop],ry[loop],rz[loop],rw[loop],
				lvx[loop],lvy[loop],lvz[loop],
				avx[loop],avy[loop],avz[loop]);

	env->ReleaseLongArrayElements(jmeHandles, handles, JNI_ABORT);
	env->ReleaseFloatArrayElements(txs, tx, JNI_ABORT);
	env->ReleaseFloatArrayElements(tys, ty, JNI_ABORT);
	env->ReleaseFloatArrayElements(tzs, tz, JNI_ABORT);
	env->ReleaseFloatArrayElements(rxs, rx, JNI_ABORT);
	env->ReleaseFloatArrayElements(rys, ry, JNI_ABORT);
	env->ReleaseFloatArrayElements(rzs, rz, JNI_ABORT);
	env->ReleaseFloatArrayElements(rws, rw, JNI_ABORT);
	env->ReleaseFloatArrayElements(lvxs, lvx, JNI_ABORT);
	env->ReleaseFloatArrayElements(lvys, lvy, JNI_ABORT);
	env->ReleaseFloatArrayElements(lvzs, lvz, JNI_ABORT);
	env->ReleaseFloatArrayElements(avxs, avx, JNI_ABORT);
	env->ReleaseFloatArrayElements(avys, avy, JNI_ABORT);
	env->ReleaseFloatArrayElements(avzs, avz, JNI_ABORT);
}

/*
 * Class:     com_jmex_physics_impl_bullet_BulletNativeInvoker
 * Method:    updateJointAxisInfo
 * Signature: (Ljava/lang/Object;IIFFFF)J
 */
JNIEXPORT jlong JNICALL Java_com_jmex_physics_impl_bullet_BulletNativeInvoker_updateJointAxisInfo
	(JNIEnv* env, jclass invokerClass, jlong jointHandle, jint axisIndex,
			jfloat availableAcceleration, jfloat desiredVelocity, jfloat posMin, jfloat posMax)
{
	g_physBridge->updateJointAxis(jointHandle,axisIndex,availableAcceleration,desiredVelocity,posMin,posMax);
}

/*
 * Class:     com_jmex_physics_impl_bullet_BulletNativeInvoker
 * Method:    applyForces
 * Signature: ([J[F[F[F[F[F[F[F[F[F)V
 */
JNIEXPORT void JNICALL Java_com_jmex_physics_impl_bullet_BulletNativeInvoker_applyForces
  (JNIEnv* env, jclass invokerClass, jlongArray jmeHandles,
		  jfloatArray fxs, jfloatArray fys, jfloatArray fzs,
		  jfloatArray pxs, jfloatArray pys, jfloatArray pzs,
		  jfloatArray txs, jfloatArray tys, jfloatArray tzs)
{
	jboolean* temp = new jboolean;
	int size = env->GetArrayLength(jmeHandles);
	jlong* handles = env->GetLongArrayElements(jmeHandles,temp);
	jfloat* fx = env->GetFloatArrayElements(fxs,temp);
	jfloat* fy = env->GetFloatArrayElements(fys,temp);
	jfloat* fz = env->GetFloatArrayElements(fzs,temp);
	jfloat* px = env->GetFloatArrayElements(pxs,temp);
	jfloat* py = env->GetFloatArrayElements(pys,temp);
	jfloat* pz = env->GetFloatArrayElements(pzs,temp);
	jfloat* tx = env->GetFloatArrayElements(txs,temp);
	jfloat* ty = env->GetFloatArrayElements(tys,temp);
	jfloat* tz = env->GetFloatArrayElements(tzs,temp);

	for(int loop=0; loop<size; loop++)
		g_physBridge->applyForces(handles[loop],
				fx[loop],fy[loop],fz[loop],
				px[loop],py[loop],pz[loop],
				tx[loop],ty[loop],tz[loop]);

	env->ReleaseLongArrayElements(jmeHandles, handles, JNI_ABORT);
	env->ReleaseFloatArrayElements(fxs, fx, JNI_ABORT);
	env->ReleaseFloatArrayElements(fys, fy, JNI_ABORT);
	env->ReleaseFloatArrayElements(fzs, fz, JNI_ABORT);
	env->ReleaseFloatArrayElements(pxs, px, JNI_ABORT);
	env->ReleaseFloatArrayElements(pys, py, JNI_ABORT);
	env->ReleaseFloatArrayElements(pzs, pz, JNI_ABORT);
	env->ReleaseFloatArrayElements(txs, tx, JNI_ABORT);
	env->ReleaseFloatArrayElements(tys, ty, JNI_ABORT);
	env->ReleaseFloatArrayElements(tzs, tz, JNI_ABORT);
}
#ifdef __cplusplus
}
#endif
